带下划线的 scala 传递函数产生的函数不是值 [英] scala passing function with underscore produces a function not a value

查看:59
本文介绍了带下划线的 scala 传递函数产生的函数不是值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写将函数传递给 map 的任何可能变体,我最初的理解是它们都会产生相同的结果,但我发现第 2、3 行实际上产生了不同的输出,第 4 行是个谜对我

Hi I was writing any possible variations of passing a function to map, my initial understanding that they would all produce the same result, but I found that the lines 2, 3, actually produced different output, and line 4 is a mystery to me

def g(v: Int) = List(v - 1, v, v + 1)
    val l = List(1, 2, 3, 4, 5)
    // map with some variations
    println(l.map { x => g(x) })
    println(l.map { (_: Int) => g(_) }) // line 2
    println(l.map { (_) => g(_) }) // line 3
    println(l.map { _ => }) // line 4
    println(l.map { g(_) })
    println(l.map { g })

输出:

List(List(0, 1, 2), List(1, 2, 3), List(2, 3, 4), List(3, 4, 5), List(4, 5, 6))
List(<function1>, <function1>, <function1>, <function1>, <function1>)
List(<function1>, <function1>, <function1>, <function1>, <function1>)
List((), (), (), (), ())
List(List(0, 1, 2), List(1, 2, 3), List(2, 3, 4), List(3, 4, 5), List(4, 5, 6))
List(List(0, 1, 2), List(1, 2, 3), List(2, 3, 4), List(3, 4, 5), List(4, 5, 6))

推荐答案

让我们从返回预期结果的那些开始:

Let's start with the ones returning the results you expected:

println(l.map { x => g(x) })
println(l.map { g(_) })
println(l.map { g })

人们可以推断出这三个是一回事.实际上,第三个依赖于 map 期望 一个函数的事实,但是,说实话,它们实际上是基本相同的.

One can infer that all three are the same thing. Actually, the third one depends on the fact that map expects a function, but, truthfully, they really are basically the same.

从最后一个开始,g 是一个命名函数.您使用名称 g 定义它,取一个 Int 并返回一个 List[Int].

Starting with the last, g is a named function. You defined it with the name g, taking an Int and returning a List[Int].

接下来,第一个:x =>g(x).这是一个匿名函数.它没有名字,它的定义就在那里,写在那里:它接受一个参数 x(它被推断为 Int),并返回一个 List[Int](因为这就是调用 g(x))的作用.

Next, the first one: x => g(x). This is an anonymous function. It doesn't have a name, and it's definition is right there, where it is written: it takes a parameter x (which was inferred to be Int), and returns a List[Int] (because that's what calling g(x)) does.

现在,gx =>g(x) 不是一回事.它们具有相同的类型Int =>List[Int],但它们是不同的函数,就像,如果我定义了 def h(x: Int) = g(x), hg 将具有相同的类型,但不会是相同的功能.

Now, g and x => g(x) are not the same thing. They have the same type, Int => List[Int], but they are different functions, just like, if I defined def h(x: Int) = g(x), h and g would have the same type but would not be the same function.

剩下g(_).这是 x => 的语法糖.g(x).在这种情况下,g(_)x =>;g(x) 真的是一回事.这是_ + _ 之类的特殊情况,下划线表示函数的参数.有人会认为 g(_) 将等于 g(x => x),但在这种情况下,扩展将是 x =>;x,是将函数移动"到下一个外部表达式边界的异常.

That leaves g(_). That is a syntactic sugar for x => g(x). In this case, g(_) and x => g(x) are really the same thing. This is a special case of something like _ + _, an expression where the underscores represent the parameters to a function. One would think that g(_) would be equal to g(x => x), but this case, where the expansion would be x => x, is an exception that "moves" the function to the next outer expression boundary.

那么,让我们看看让你产生怀疑的案例:

So, let's see the cases that gave you doubts:

println(l.map { (_: Int) => g(_) }) // line 2

首先,我们知道 g(_)x =>g(x),所以这行等价于

First, we know that g(_) is the same thing as x => g(x), so this line would be equivalent to

println(l.map { (_: Int) => (x => g(x)) }) // line 2

剩下的下划线与g(_)中的下划线完全无关.下划线代替参数名称意味着参数名称无关.本质上和写这个是一样的:

The remaining underscore is completely unrelated to the one in g(_). An underscore in place of a parameter name means the parameter name is irrelevant. It's essentially the same thing as writing this:

println(l.map { (unusedVar: Int) => (x => g(x)) }) // line 2

至于类型,是Int =>(Int => List[Int]).因此,当您映射列表时,您会得到一个 Int => 列表.List[Int]--函数!-- 这就是打印出来的内容.

As for the type, it is Int => (Int => List[Int]). So, when you map the list, you get a list of Int => List[Int]-- functions! -- which is what gets printed.

println(l.map { (_) => g(_) }) // line 3

与第 2 行相同,只是省略了参数的类型,无论如何都会对其进行推断.

Same thing as line 2, except that you omit the type of the parameter, which is going to be inferred anyway.

最后,

println(l.map { _ => }) // line 4

类型是 Int =>单位.它只接受一个参数,该参数被忽略,不执行任何操作,并返回一个 Unit(类似于 Java 中的 void 类型).

The type of that is Int => Unit. It simply takes a parameter, which is ignored, doesn't do anything, and returns a Unit (which is something like the void type in Java).

Unit 是值无关紧要的事物的类型.一个函数必须返回一些东西,因为这就是函数所做的.当这件事无关紧要时,我们使用 Unit 类型,它只有一个值.Unit 的唯一值写为 ().

Unit is a type for things whose value doesn't matter. A function has to return something, because that's what functions do. When that something doesn't matter, we use the Unit type, which has only one value. The sole value of Unit is written as ().

例如,返回true:

def test = {
  val a = println("Println returns Unit")
  val b: Unit = () // the only possible value
  a == b
}

这就是为什么你看到 () 的列表被打印在第 4 行:它是一个 List[Unit],因此,它的所有元素都是 <代码>().

And that's why you see a list of () get printed for line 4: it's a List[Unit], and, therefore, all elements of it are ().

这篇关于带下划线的 scala 传递函数产生的函数不是值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆