在 Scala 中定义函数的两种方法。有什么区别?

发布于 2024-10-17 11:03:31 字数 1284 浏览 1 评论 0原文

这是一个定义并尝试一些功能的 Scala 会话:

scala> def test1(str: String) = str + str;    
test1: (str: String)java.lang.String

scala> test1("ab")
res0: java.lang.String = abab

效果很好。

scala> val test2 = test1
<console>:6: error: missing arguments for method test1 in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
       val test2 = test1
                   ^

哎呀。

scala> val test2 = test1 _
test2: (String) => java.lang.String = <function1>

scala> test2("ab")
res1: java.lang.String = abab

效果很好!

现在,我已经看到了折叠时的 _ 语法(_ + _ 等)。据我了解, _ 基本上意味着“一个论点”。所以 test1 _ 基本上意味着一个带有参数的函数,该函数被赋予 test1”。但是为什么这不完全与刚才的相同test1?为什么如果我附加一个_会有区别?

所以我一直在探索......

scala> val test3 = (str: String) => str + str
test3: (String) => java.lang.String = <function1>

scala> test3("ab")
res2: java.lang.String = abab

scala> val test4 = test3
test4: (String) => java.lang.String = <function1>

这里没有_有什么区别!在 defed 函数和 valed 函数之间?

Here is a little Scala session that defines and tries out some functions:

scala> def test1(str: String) = str + str;    
test1: (str: String)java.lang.String

scala> test1("ab")
res0: java.lang.String = abab

works nicely.

scala> val test2 = test1
<console>:6: error: missing arguments for method test1 in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
       val test2 = test1
                   ^

oops.

scala> val test2 = test1 _
test2: (String) => java.lang.String = <function1>

scala> test2("ab")
res1: java.lang.String = abab

works well!

Now, I've seen the _ syntax when folding (_ + _, etc). So as I understand it _ basically means "an argument". So test1 _ basically means a function with an argument, which is given to test1". But why isn't that exactly the same as just test1? Why is there a difference if I append a _?

So I kept exploring...

scala> val test3 = (str: String) => str + str
test3: (String) => java.lang.String = <function1>

scala> test3("ab")
res2: java.lang.String = abab

scala> val test4 = test3
test4: (String) => java.lang.String = <function1>

Here it works without _! What's the difference between a defed function, and a valed function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

溇涏 2024-10-24 11:03:31

def 在周围的对象/类/特征中声明一个方法,类似于在 Java 中定义方法的方式。您只能在其他对象/类/特征中使用 def。在 REPL 中,您看不到周围的对象,因为它是“隐藏的”,但它确实存在。

您不能将 def 分配给值,因为 def 不是值 - 它是对象中的方法。

(x: T) => x * x 声明并实例化一个在运行时存在的函数对象。函数对象是扩展 FunctionN 特征的匿名类的实例。 FunctionN 特征带有一个 apply 方法。名称 apply 很特殊,因为它可以省略。表达式f(x)被脱糖为f.apply(x)

底线是 - 由于函数对象是存在于堆上的运行时值,因此您可以将它们分配给值、变量和参数,或者从方法中将它们作为返回值返回。

为了解决将方法分配给值的问题(这可能很有用),Scala 允许您使用占位符从方法创建函数对象。上面示例中的表达式 test1 _ 实际上在方法 test1 周围创建了一个包装函数 - 它相当于 x =>;测试1(x)。

The def declares a method within a surrounding object/class/trait, similar to the way you define methods in Java. You can only use defs within other objects/classes/traits. In the REPL, you cannot see the surrounding object because it's "hidden", but it does exist.

You cannot assign a def to a value, because the def is not a value - it's a method in the object.

The (x: T) => x * x declares and instantiates a function object, which exists at runtime. Function objects are instances of anonymous classes which extend FunctionN traits. FunctionN traits come with an apply method. The name apply is special, because it can be omitted. Expression f(x) is desugared into f.apply(x).

The bottomline is - since function objects are runtime values which exist on the heap, you can assign them to values, variables and parameters, or return them from methods as return values.

To solve the issue of assigning methods to values (which can be useful), Scala allows you to use the placeholder character to create a function object from a method. Expression test1 _ in your example above actually creates a wrapper function around the method test1 - it is equivalent to x => test1(x).

窗影残 2024-10-24 11:03:31

def'ed 函数和 val'ed 函数之间没有区别:

scala> def test1 = (str: String) => str + str
test1: (String) => java.lang.String

scala> val test2 = test1
test2: (String) => java.lang.String = <function1>

scala> val test3 = (str: String) => str + str
test3: (String) => java.lang.String = <function1>

scala> val test4 = test2
test4: (String) => java.lang.String = <function1>

看到了吗?所有这些都是函数,由 X => 表示。他们有 Y 类型。

scala> def test5(str: String) = str + str
test5: (str: String)java.lang.String

您看到 X => 了吗? Y 类型?如果你这样做,请去看眼科医生,因为没有眼科医生。这里的类型是(X)Y,通常用来表示方法

实际上,test1test2test3test4都是方法,它们返回函数。 test5 是一个返回java.lang.String 的方法。此外,test1test4 不带参数(无论如何,只有 test1 可以),而 test5 则带参数。

所以,区别非常简单。在第一种情况下,您尝试将一个方法分配给一个 val,但没有填写该方法采用的参数。所以它失败了,直到你添加了一个尾部下划线,这意味着将我的方法变成一个函数

在第二个示例中,您有一个函数,因此您不需要执行任何其他操作。

方法不是函数,反之亦然。函数是 FunctionN 类之一的对象。方法是与对象关联的某些代码段的句柄。

请参阅 Stack Overflow 上有关方法与函数的各种问题。

There's no difference between a def'ed function and a val'ed function:

scala> def test1 = (str: String) => str + str
test1: (String) => java.lang.String

scala> val test2 = test1
test2: (String) => java.lang.String = <function1>

scala> val test3 = (str: String) => str + str
test3: (String) => java.lang.String = <function1>

scala> val test4 = test2
test4: (String) => java.lang.String = <function1>

See? All of these are functions, which is indicated by the X => Y type they have.

scala> def test5(str: String) = str + str
test5: (str: String)java.lang.String

Do you see an X => Y type? If you do, go see an ophthalmologist, because there's none. The type here is (X)Y, commonly used to denote a method.

Actually, test1, test2, test3 and test4 are all methods, which return functions. test5 is a method which returns a java.lang.String. Also, test1 through test4 do not take parameters (only test1 could, anyway), while test5 does.

So, the difference is pretty simple. In the first case, you tried to assign a method to a val, but did not fill in the parameters the method take. So it failed, until you added a trailing underscore, which meant turn my method into a function.

In the second example you had a function, so you didn't need to do anything else.

A method is not a function, and vice versa. A function is an object of one of the FunctionN classes. A method is a handle to some piece of code associated with an object.

See various questions about methods vs functions on Stack Overflow.

伏妖词 2024-10-24 11:03:31

下划线在不同的上下文中表示不同的含义。但它总是可以被认为是会出现在这里的东西,但不需要命名

当应用代替参数时,效果是将方法提升为函数。

scala> def test1(str: String) = str + str; 
test1: (str: String)java.lang.String

scala> val f1 = test1 _
f1: (String) => java.lang.String = <function1>

注意,该方法已经变成了类型为(String) => 的函数。细绳。

Scala 中方法和函数之间的区别在于方法类似于传统的 Java 方法。您不能将它们作为值传递。然而,函数本身就是值,可以用作输入参数和返回值。

提升还可以更进一步:

scala> val f2 = f1 _
f2: () => (String) => java.lang.String = <function0>

提升这个功能会产生另一个功能。这次的type() => (字符串)=> (字符串)

据我所知,这种语法相当于用下划线显式替换所有参数。例如:

scala> def add(i: Int, j: Int) = i + j
add: (i: Int,j: Int)Int

scala> val addF = add(_, _)
addF: (Int, Int) => Int = <function2>

scala> val addF2 = add _    
addF2: (Int, Int) => Int = <function2>

The underscore means different things in different contexts. But it can always be thought of as the thing that would go here, but doesn't need to be named.

When applied in place of parameters, the effect is to lift the method to a function.

scala> def test1(str: String) = str + str; 
test1: (str: String)java.lang.String

scala> val f1 = test1 _
f1: (String) => java.lang.String = <function1>

Note, the method has become a function of type (String) => String.

The distinction between a method and a function in Scala is that methods are akin to traditional Java methods. You can't pass them around as values. However functions are values in their own right and can be used as input parameters and return values.

The lifting can go further:

scala> val f2 = f1 _
f2: () => (String) => java.lang.String = <function0>

Lifting this function results in another function. This time of type () => (String) => (String)

From what I can tell, this syntax is equivalent to substituting all of the parameters with an underscore explicitly. For example:

scala> def add(i: Int, j: Int) = i + j
add: (i: Int,j: Int)Int

scala> val addF = add(_, _)
addF: (Int, Int) => Int = <function2>

scala> val addF2 = add _    
addF2: (Int, Int) => Int = <function2>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文