Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 高阶函数映射_Scala - Fatal编程技术网

Scala 高阶函数映射

Scala 高阶函数映射,scala,Scala,这些说法之间有什么区别 val numbers = List(1, 2, 3, 4) numbers map println // vs. numbers map (x => println(x)) val numbers = List(1, 2, 3, 4) numbers map println // vs. numbers map (x => println(x)) Scala如何知道println会重复处理每个数字 谢谢。map需要一个函数,该函数可以计算一个值并生成一个

这些说法之间有什么区别

val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
Scala如何知道println会重复处理每个数字


谢谢。

map
需要一个函数,该函数可以计算一个值并生成一个值。在第一个示例中,通过给出lambda显式地提供这样一个函数。在第二种情况下,编译器可以检查类型并查看
println:A=>Unit
。请注意,通常情况下,您不希望将
map
用于生成
Unit
的函数,这更适合于
foreach

map
所期望的函数为一个值并生成一个值。在第一个示例中,通过给出lambda显式地提供这样一个函数。在第二种情况下,编译器可以检查类型并查看
println:A=>Unit
。请注意,通常情况下,您不希望将
map
用于生成
Unit
的函数,这更适合于
foreach

这两个语句具有相同的语义,第二个版本只是添加了一个间接级别,而实际工作并不需要它

问题是map函数将一个函数作为参数,该函数能够对Int进行运算并生成一个单位:

final def map[B](f: (A) ⇒ B): List[B]
在你的例子中,A是Int,B是Unit

现在,如果您查看println方法的签名和匿名函数的签名,您会注意到它们实际上是相同的:

def println(x: Any): Unit
(x => println(x)): Any -> Unit
所发生的事情是map函数迭代列表中的元素,并为每个元素x调用函数f(x)。因为println和匿名函数都接受Any作为输入,所以映射可以安全地将x Int传递给它们


使用匿名函数,您只是添加了一个中间函数调用步骤。

这两个语句具有相同的语义,第二个版本只是添加了一个间接级别,而实际工作并不需要它

问题是map函数将一个函数作为参数,该函数能够对Int进行运算并生成一个单位:

final def map[B](f: (A) ⇒ B): List[B]
在你的例子中,A是Int,B是Unit

现在,如果您查看println方法的签名和匿名函数的签名,您会注意到它们实际上是相同的:

def println(x: Any): Unit
(x => println(x)): Any -> Unit
所发生的事情是map函数迭代列表中的元素,并为每个元素x调用函数f(x)。因为println和匿名函数都接受Any作为输入,所以映射可以安全地将x Int传递给它们

使用匿名函数只是添加一个中间函数调用步骤

这些说法之间有什么区别

val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
map
将转换单个元素的函数作为其参数<代码>映射然后将此函数应用于每个元素,并返回一个包含已转换元素的集合。(顺便说一句,这就是为什么这个代码没有意义:a)忽略
map
的返回值,b)
println
总是返回
Unit
,因此您将得到一个
Unit
的列表
foreach
将是此处使用的正确方法。)

在第二个示例中,将λ(匿名一级函数对象)传递给
map

在第一个示例中,您将传递什么到
map
?看起来您正在传递一个方法,但这不可能是:a)
map
接受一个函数,而不是一个方法,b)方法不是对象,因此您根本无法传递它们。您必须以某种方式将方法转换和/或包装到函数中

在第二个示例中,您非常明确地做到了这一点:您有一个调用该方法的函数。第一个例子更加含蓄。Scala有一个名为η-expansion的特性,它允许您“提升”一个方法来执行函数,该函数将部分地将该方法应用于它的隐式
这个
参数,但不绑定它的其他(常规)参数

其语法是无处不在的下划线:
foo.bar
表示“采用
foo
bar
方法,将其
this
绑定到
foo
并将其转换为函数”。在这种特殊情况下,您使用
println
,将其
this
绑定到顶级REPL上下文对象(这并不重要,因为
println
实际上并不关心它的
this
,它就像一个过程一样使用),并将其转换为一个函数

但是等等,没有下划线?这是正确的。如果Scala编译器可以确定您实际上不想调用该方法,而是将其包装到函数中(即,当您不传递参数列表时,该方法需要参数列表,而上下文需要与该方法的类型兼容的类型),则Scala将为您执行隐式η-扩展

那么,让我们回到你的问题:

这些说法之间有什么区别

val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
好的,一方面,区别是我上面描述的:第一个例子使用隐式η展开,第二个例子使用显式λ展开。OTOH,没有区别:它们都是从
println
方法创建函数的,第二个方法只是以一种更复杂的方式创建函数

Scala如何知道println会重复处理每个数字

没有。a) 不是
println
负责“处理每个数字”,而是
map
负责,b)Scala什么都不知道,这就是
map
的编写方式

非常简单,
map
如下所示:

sealed trait MyList[+T] {
  def map[U](function: T ⇒ U): MyList[U]
  def foreach(procedure: T ⇒ Unit)
}

case object EmptyList extends MyList[Nothing] {
  // mapping the empty list returns the empty list
  def map[U](function: Nothing ⇒ U) = EmptyList

  def foreach(procedure: Nothing ⇒ Unit) = ()
}

final case class ListCell[+T](first: T, rest: MyList[T]) extends MyList[T] {
  // mapping a non-empty list returns the result of transforming the first 
  // element of the list and recursively mapping the rest of the list
  def map[U](function: T ⇒ U) = ListCell(function(first), rest map function)

  def foreach(procedure: T ⇒ Unit) = { procedure(first); rest foreach procedure }
}
下面是我们如何使用简单的小列表:

val list: MyList[Short] = ListCell(1, ListCell(2, ListCell(3, EmptyList)))

list map (1+)
// => ListCell(2, ListCell(3, ListCell(4, EmptyList)))

list map(_.toString)
// => ListCell(1, ListCell(2, ListCell(3, EmptyList)))

list map println
// 1
// 2
// 3
// => ListCell((), ListCell((), ListCell((), EmptyList)))
// here you can see the useless list of Units that is returned

list foreach println
// 1
// 2
// 3
// foreach just returns nothing
这些说法之间有什么区别

val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
val numbers = List(1, 2, 3, 4)
numbers map println
// vs.
numbers map (x => println(x))
map
将转换单个元素的函数作为其参数<代码>映射
然后将此函数应用于每个元素并返回一个列