简体   繁体   English

Scala语法帮助咖喱

[英]Scala Syntax Help Currying

I came across some code in scala in a similar form like this: 我在scala中以类似的形式遇到了一些代码,如下所示:

  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? 我很困惑,所以函数test1将一个函数和一个Int作为参数,然后返回一个函数,对吗? Then how can test1(x => 2*x) be valid and returns a function to test2? 那么test1(x => 2*x)如何有效并将函数返回给test2? Apparently it takes 2 asthe integer parameter, but why? 显然,它需要2作为整数参数,但是为什么呢? How does the statement test2(test1(x => 2*x))(2) expand? 语句test2(test1(x => 2*x))(2)扩展?

Thanks in advance. 提前致谢。

function test1 takes a function and a Int as parameters, and returns a function, right? 函数test1将一个函数和一个Int作为参数,然后返回一个函数,对吗?

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. 然后,返回的函数将int作为参数并返回int。

Then how can test1(x => 2*x) be valid and returns a function to test2? 那么test1(x => 2 * x)如何有效并将函数返回给test2?

I hope that's clear now. 我希望现在很清楚。

How does the statement test2(test1(x => 2*x))(2) expand? 语句test2(test1(x => 2 * x))(2)如何扩展?

test1 is called with x => 2*x as the argument and returns a function. 使用x => 2*x作为参数调用test1并返回一个函数。 Then test2 is called with that returned function as its argument and returns another function. 然后以返回的函数作为参数调用test2并返回另一个函数。 Then that other function is called with 2 as its argument. 然后使用2作为参数调用另一个函数。

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. Scala具有多个参数列表的方法可以像其他语言中的咖喱函数一样工作,但实际上是作为需要其所有参数的方法实现的,这确实在语法中得以体现。 For example if you put this into the REPL: 例如,如果将其放入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. 此语法允许的是“ eta扩展”,其中方法被转换为函数。 If you write: 如果您写:

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

You can get a function that represents test1 partially applied. 您可以获得代表部分应用的test1的函数。 Scala will do eta-expansion automatically if the context requires it, which is what happens with test2(test1(x => 2*x))(2) . 如果上下文需要,Scala将自动执行eta扩展,这就是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. 请注意, test1本身从不返回函数,但编译器将在需要时基于该函数构建函数。

However, if you define test1 like: 但是,如果您像这样定义test1

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

Then the compiler will accept test1(x => 2*x) without the _ . 然后,编译器将接受不带_ test1(x => 2*x) 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. 同样,在基础实现中,只有一个类实现由test1处理的闭包,而对于原始定义, test1每个部分应用都会为其创建一个新类。 On the other hand, it is less efficient when given both parameters, because the closure is always created. 另一方面,给定两个参数时效率较低,因为总是创建闭包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM