Question

Could you please explain to me how to write shortened version of function literal ?

I'm going through this Spray tutorial in which following code

val route: Route = { ctx => ctx.complete("yeah") }

get compressed to

val route: Route = complete("yeah")

where complete is function of RouteDirectives.

I cannot reproduce the same in my code which is

class Test
{
  def testFunc(value : Int) {
    println(value)
  }
}

type MyType = Test => Unit
val asd : MyType = _.testFunc(10)
asd(new Test)

If I write val asd : MyType = testFunc(10) instead I (obviously) get error

error: type mismatch;
found   : Int(10)
required: Int => Unit
val asd : MyType = testFunc(10)

So I thought maybe 'complete' is also an object with apply method. And indeed following works

val route: Route = complete.apply("yeah")

But I don't see an object. In the debugger it steps into RouteDirectives.complete as expected.

Why ? What am I missing ?

Was it helpful?

Solution

complete returns a function. When you call complete("yeah"), you are supplying the "yeah" parameter to that function (they call it the magnet).

So to do something similar you would write:

def testFunc: Int => Unit = (i: Int) => println(i)

Putting it together with calling a method on an object Test:

def testFunc: Int => (Test => Unit) = (i: Int) => {
  (test: Test) => println(i)
}

Because of the way => associates to the right and type inference, this could be rewritten:

def testFunc: Int => Test => Unit = i => test => println(i)

It is then either very confusing or natural (the parameters mirror the types exactly).

So when in the tutorial they say it is equivalent, the authors of the library go to some length to make it look like it is "equivalent" by returning functions, it is not something that is built-in in the Scala syntax.

OTHER TIPS

I think you had a formatting error in your code. When I first pasted your code into the REPL, the new line after "class Test" resulted in the next block being treated as an entirely separate block. Did you execute that in the REPL? The following worked for me:

scala> class Test { def testFunc(i: Int) { println(i) } }
defined class Test

scala> type MyType = Test => Unit
defined type alias MyType

scala> val asd : MyType = { t => t.testFunc(10) }
asd: Test => Unit = <function1>

scala> val asd : MyType = { _.testFunc(10) }
asd: Test => Unit = <function1>

scala> val asd : MyType = _.testFunc(10)
asd: Test => Unit = <function1>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top