Scala:什么时候需要在map函数前面加一个点?

Scala:什么时候需要在map函数前面加一个点?,scala,Scala,我认为集合和映射函数之间的点是可选的,但似乎故事的内容不止这些 这两种格式都适用: scala> List(1,2,3) map (_*2) res6: List[Int] = List(2, 4, 6) scala> List(1,2,3).map (_*2) res7: List[Int] = List(2, 4, 6) 这失败了: scala> articleFiles map (file => (file \\ "contentitem").map( a =&

我认为集合和映射函数之间的点是可选的,但似乎故事的内容不止这些

这两种格式都适用:

scala> List(1,2,3) map (_*2)
res6: List[Int] = List(2, 4, 6)

scala> List(1,2,3).map (_*2)
res7: List[Int] = List(2, 4, 6)
这失败了:

scala> articleFiles map (file => (file \\ "contentitem").map( a => (a \ "@id").text) ).flatten
<console>:17: error: missing parameter type
       articleFiles map (file => (file \\ "contentitem").map( a => (a \ "@id").text) ).flatten
                         ^

注意,最后两个示例之间的唯一区别是
articleFiles.map

中的点。在Scala中,运算符是方法,可以这样处理。我们可以使用句点作为方法调用map,也可以简单地将其作为运算符使用
至于第一个失败而第二个失败的原因,第二个例子比第一个例子要明确得多。编译器知道在方法调用中预期的变量类型,但在运算符调用中,它更不明确(可能是AnyVal),因此抛出缺少的参数类型。
简单地说,当堆叠映射并使用不同的调用时,编译器无法决定应该使用哪种变量类型

您不能在一条链中混合使用带有和不带有
的调用,因此

articleFiles map (file => (file \\ "contentitem").map( a => (a \ "@id").text) ).flatten
意味着


这显然是行不通的:函数没有
flant
方法。发生此特定错误的原因是,匿名函数中的参数类型只能在预期函数类型的上下文中使用时才能忽略,而这不是这样的上下文。

只需补充一点,有两种工具可以显示代码中发生的情况,特别是推断出的参数和类型

scala> val vs = (1 to 10).toList
vs: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vs.map(Option.apply)
res0: List[Option[Int]] = List(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(10))

scala> vs.map(Option.apply).flatten
res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vs map(Option.apply).flatten
<console>:13: error: missing argument list for method apply in object Option
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `apply _` or `apply(_)` instead of `apply`.
       vs map(Option.apply).flatten
                     ^

scala> vs map(Option.apply(_)).flatten
<console>:13: error: missing parameter type for expanded function ((x$1: <error>) => Option.apply(x$1))
       vs map(Option.apply(_)).flatten
                           ^

scala> vs map(Option.apply(_)).flatten // show
[snip]
      val res4 = vs.map(((x$1) => Option apply x$1).flatten)

<console>:13: error: missing parameter type for expanded function ((x$1: <error>) => Option.apply(x$1))
       vs map(Option.apply(_)).flatten // show
                           ^
scala>val vs=(1到10)。toList
vs:List[Int]=List(1,2,3,4,5,6,7,8,9,10)
scala>vs.map(Option.apply)
res0:List[Option[Int]=List(一些(1),一些(2),一些(3),一些(4),一些(5),一些(6),一些(7),一些(8),一些(9),一些(10))
scala>vs.map(Option.apply)。展平
res1:List[Int]=List(1,2,3,4,5,6,7,8,9,10)
scala>vs贴图(Option.apply)。展平
:13:错误:缺少对象选项中应用方法的参数列表
未应用的方法仅在需要函数类型时才会转换为函数。
您可以通过编写'apply'或'apply()`而不是'apply'来明确此转换。
vs贴图(选项。应用)。展平
^
scala>vs贴图(选项.应用()).展平
:13:错误:缺少扩展函数的参数类型((x$1:)=>选项。应用(x$1))
vs贴图(选项。应用())。展平
^
scala>vs-map(Option.apply()).flant//show
[剪报]
val res4=vs.map(((x$1)=>选项应用x$1)。展平)
:13:错误:缺少扩展函数的参数类型((x$1:)=>选项。应用(x$1))
vs映射(Option.apply()).flant//show
^

这是由引起的,但您可以使用空格代替圆点,使用
展平
,它应该可以工作。这种语法称为后缀表示法,它是。我更喜欢使用点表示法,因为它更容易读取流,并使用诸如
flatte
toList
等方法。问题在于
.flatte
调用,而不是
.map
。分号推断不是这里的问题:在这两种情况下,分号都位于行尾,根据需要。最后尝试移除展平,现在再次尝试展平,但不要使用点,而是使用空格。您将看到这两种方法都是有效的。编译器应该说存在一个具有预期类型a函数的封闭上下文。类似于。show/comment指令非常酷,但它看起来像一个魔术——所以我会在答案中明确描述它的作用,因为人们可能会认为这只是一个注释(特别是如果你忘记在
/
show
之间加空格)@dk14我最近修复了恼人的空格问题。我试图传播这些技巧,但是,对于SO的高标准的完整答案来说,我太懒了。因此,需要一个AI来合并重复项并整合信息。也许我会添加一些我也会添加的工作示例:
vs map(Option.apply)flatte
(这将显示有关高级语言功能的警告)后缀表示法的唯一潜在问题是分号推断
articleFiles.map((file => (file \\ "contentitem").map( a => (a \ "@id").text) ).flatten)
scala> val vs = (1 to 10).toList
vs: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vs.map(Option.apply)
res0: List[Option[Int]] = List(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(10))

scala> vs.map(Option.apply).flatten
res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vs map(Option.apply).flatten
<console>:13: error: missing argument list for method apply in object Option
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `apply _` or `apply(_)` instead of `apply`.
       vs map(Option.apply).flatten
                     ^

scala> vs map(Option.apply(_)).flatten
<console>:13: error: missing parameter type for expanded function ((x$1: <error>) => Option.apply(x$1))
       vs map(Option.apply(_)).flatten
                           ^

scala> vs map(Option.apply(_)).flatten // show
[snip]
      val res4 = vs.map(((x$1) => Option apply x$1).flatten)

<console>:13: error: missing parameter type for expanded function ((x$1: <error>) => Option.apply(x$1))
       vs map(Option.apply(_)).flatten // show
                           ^