Scala Syntax Help Currying

北慕城南 提交于 2019-12-11 04:01:29

问题


I came across some code in scala in a similar form like this:

  def test1(f : Int => Int)(x : Int) = x + f(x)

  def test2(f : Int => Int)(x : Int) = f(x)

  test2(test1(x => 2*x))(2)

I'm confused, so function test1 takes a function and a Int as parameters, and returns a function, right? Then how can test1(x => 2*x) be valid and returns a function to test2? Apparently it takes 2 asthe integer parameter, but why? How does the statement test2(test1(x => 2*x))(2) expand?

Thanks in advance.


回答1:


This:

test2(test1(x => 2*x))(2)

expands to this:

test2(y => test1(x => 2*x)(y))(2)

Scala's methods with multiple argument lists can act a lot like curried functions in other languages, but in fact are implemented as methods that requires all of their parameters, and this does show through in the syntax. For example if you put this into the REPL:

test1(x => 2*x)

It will complain about missing arguments. What this syntax does allow is "eta-expansion", where a method is converted into a function. If you write:

val func: Int => Int = test1(x => 2*x) _

You can get a function that represents test1 partially applied. Scala will do eta-expansion automatically if the context requires it, which is what happens with test2(test1(x => 2*x))(2). Note that test1 itself never returns a function, but the compiler will build a function based on it when required.

However, if you define test1 like:

def test1(f : Int => Int) = (x : Int) => x + f(x)

Then the compiler will accept test1(x => 2*x) without the _. Also, in the underlying implementation there will be only one class implementing the closure retured by test1, whereas with the original definition every partial application of test1 causes a new class to be created for it. On the other hand, it is less efficient when given both parameters, because the closure is always created.




回答2:


function test1 takes a function and a Int as parameters, and returns a function, right?

No, it only takes a function as its argument and returns a function. The returned function then takes an int as the argument and returns an int.

Then how can test1(x => 2*x) be valid and returns a function to test2?

I hope that's clear now.

How does the statement test2(test1(x => 2*x))(2) expand?

test1 is called with x => 2*x as the argument and returns a function. Then test2 is called with that returned function as its argument and returns another function. Then that other function is called with 2 as its argument.



来源:https://stackoverflow.com/questions/24086444/scala-syntax-help-currying

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!