gpt4 book ai didi

function - 这两种结构之间的根本区别是什么?

转载 作者:行者123 更新时间:2023-12-02 19:45:17 26 4
gpt4 key购买 nike

Possible Duplicate:
Difference between method and function in Scala

scala> val x1 : (Int) => Int = (x) => x + 1
x1: (Int) => Int = <function>

scala> def x2 (x : Int) = x + 1
x2: (Int)Int

scala> x1(1)
res0: Int = 2

scala> x2(1)
res1: Int = 2

x1 和 x2 之间的实际区别是什么。您能否举例说明何时使用这两种结构?

最佳答案

在 Scala 中,这是两个从用户角度来看很相似但从 JVM 角度来看完全不同的构造。 x1是一个“函数对象”并且 x2是一种方法。

代码示例

class Test
{
val x1 = (x: Int) => x + 3
def x2(x: Int) = {
def x3(y: Int) = y + 10
x3(x) + 3
}
}

方法

在 Scala 中,def定义一个直接编译为JVM方法的方法,并且它必须属于某个Java类。

在上面的代码片段中,x2x3被编译为 JVM 方法,属于 class Test ,甚至 x3定义在方法内部(嵌套方法)。

您可以使用 javap -private Test 来验证这一点编译代码后。它将输出以下消息:

brianhsu@USBGentoo ~/test $ javap -private Test
Compiled from "test.scala"
public class Test extends java.lang.Object implements scala.ScalaObject{
private final scala.Function1 x1;
public scala.Function1 x1();
public int x2(int);
private final int x3$1(int);
public Test();
}

你可以看到x2只是一个普通的Java方法,x3被重命名为x3$1(以避免在其他方法中存在另一个x3时发生名称冲突),但从JVM的角度来看它仍然是一个普通的Java方法。

函数对象

我使用这个术语是为了避免混淆,这就是你用val x1 = (x: Int) => x + 1之类的东西定义的。 .

你使用的时候可能看起来像方法,但实际上它和你用def定义的方法完全不同。 s。

那么val x1 = (x: Int) => x + 2又是什么呢?意味着什么?

嗯,Scala 中有称为 Function0、Function1、Function2、Function3...Function22 的特征。

它看起来像下面这样(我已经简化了):

// T1 is the type of parameter 1, R is the type of return value
triat Function1[T1, R] {
def apply(t1: T1): R
}

当你写val x1 = (x: Int) => x + 2时,Scala 编译器将生成一个实现特征 Function1 的对象,它可能如下所示:

val t = new Function1[Int, Int] { 
def apply(t1: Int) = t1 + 2
}

当你写x1(3)时,实际上Scala只是将其转换为t.apply(3)。

所以,函数对象不是方法,它只是一个普通的Java对象,它有一个名为apply的方法。 ,Scala编译器给你一个语法糖,不必显式调用apply当你使用它们时。

您可以使用 javap 来验证这一点再次。

brianhsu@USBGentoo ~/test $ javap Test\$\$anonfun\$1 
Compiled from "test.scala" public final class Test$$anonfun$1 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable{
public static final long serialVersionUID;
public static {};
public final int apply(int);
public int apply$mcII$sp(int);
public final java.lang.Object apply(java.lang.Object);
public Test$$anonfun$1(Test);
}

brianhsu@USBGentoo ~/test $ javap -private Test
Compiled from "test.scala" public class Test extends java.lang.Object implements scala.ScalaObject{
private final scala.Function1 x1;
public scala.Function1 x1();
public int x2(int);
private final int x3$1(int);
public Test();
}

您会注意到有一个额外的 .class 文件,名为 Test$$anonfun$1.class ,即 (x: Int) => x + 2 类,您会注意到有一个 x1类型为 Function1 的私有(private)变量一个x1()方法返回 scala.Function1 .

x1()方法,因为 Scala 实现了统一访问原则。但幕后是x1()方法只返回 Test$$anonfun$1 的函数对象实例类。

结论

也许方法和函数看起来相同,但它们是不同的东西。 Scala 编译器帮助我们毫不费力地将它们一起使用。

大多数时候你不会关心它们之间的区别,但确实有时有些东西需要一个函数对象,而你只有方法。

在这种情况下,编译器会告诉你添加 _在方法名称之后将其提升为函数对象。

更新

下面是一个有趣的代码示例,显示了方法和函数对象之间的差异:您可以定义一个带有 25 个参数的方法,但不能定义一个带有超过 22 个参数的函数对象。

class Test2
{
def x (
x01: Int, x02: Int, x03: Int, x04: Int, x05: Int,
x06: Int, x07: Int, x08: Int, x09: Int, x10: Int,
x11: Int, x12: Int, x13: Int, x14: Int, x15: Int,
x16: Int, x17: Int, x18: Int, x19: Int, x20: Int,
x21: Int, x22: Int, x23: Int, x24: Int, x25: Int
) = 0

// Compile error:
// implementation restricts functions to 22 parameters

/*
val y = (
x01: Int, x02: Int, x03: Int, x04: Int, x05: Int,
x06: Int, x07: Int, x08: Int, x09: Int, x10: Int,
x11: Int, x12: Int, x13: Int, x14: Int, x15: Int,
x16: Int, x17: Int, x18: Int, x19: Int, x20: Int,
x21: Int, x22: Int, x23: Int, x24: Int, x25: Int
) => 0
*/
}

关于function - 这两种结构之间的根本区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7571319/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com