Scala部分应用模式匹配函数

Scala部分应用模式匹配函数,scala,Scala,我发布这个问题是出于好奇,想看看是否有人知道在以下情况下模式匹配是如何工作的。假设我有一个函数值,定义如下: val f = (s: String) => s.toInt val f2 = f(_: String) match { case i: Int => i + 2 } scala> f2("3") res0: Int = 5 它的类型当然是String=>Int。现在我想创建一个基于模式匹配的新函数,该模式匹配传递给该函数的任何内容的输出。我可以这样定义: v

我发布这个问题是出于好奇,想看看是否有人知道在以下情况下模式匹配是如何工作的。假设我有一个函数值,定义如下:

val f = (s: String) => s.toInt
val f2 = f(_: String) match {
  case i: Int => i + 2
}
scala> f2("3")
res0: Int = 5
它的类型当然是String=>Int。现在我想创建一个基于模式匹配的新函数,该模式匹配传递给该函数的任何内容的输出。我可以这样定义:

val f = (s: String) => s.toInt
val f2 = f(_: String) match {
  case i: Int => i + 2
}
scala> f2("3")
res0: Int = 5
现在我的新函数也是来自String=>Int,但在这个过程中它添加了2。它可以被称为:

val f = (s: String) => s.toInt
val f2 = f(_: String) match {
  case i: Int => i + 2
}
scala> f2("3")
res0: Int = 5
如果我在不执行部分应用程序的情况下执行相同的操作,则会根据函数本身获得匹配:

val f3 = f match {
  case x => "matched: " + x
}
现在,值f3被指定为“matched”,因为它使用“f”作为值调用match

所以我的问题是,Scala如何区分这两者?它们都是函数值,并且都是String=>Int类型。事实上,如果在运行match之前将部分应用的函数值分配给临时变量tmp,则其行为与f3相同:

val tmp = f(_: String)
val f4 = tmp match {
  case x => "matched: " + x
}
现在,f4被指定为“matched”,而不是一个函数字符串=>Int


我可以看出想要做这两件事的价值,我只是好奇它是如何做到的。这只是一个神奇的Scala,不知怎么的,它发现你在匹配的上下文中部分应用了一个函数,所以它会生成一些不同的东西…

下划线就是这样工作的

f(_: String) match {
  case i: Int => i + 2
}
是英语的简写

(x: String) => (f(x) match {
  case i: Int => i + 2
})
(添加括号以使事情更清楚)但您的其他示例与

(x: String => f(x)) match {
  case y => "matched: " + y
}

不确定我是否相信。在第二个示例中,函数值f只是一个值,因此不需要进行(x:String=>f(x))匹配{..}。事实上,在匹配完成之前,它没有从任何地方输入的值x。大小写只匹配类型为(String=>Int)的值,因此f match{…}就足够了。我买第一个例子。这意味着val tmp=(x:String)=>f(x),然后传递给match。@Mike不需要eta扩展f,但f在功能上等同于它的eta扩展(x:String=>f(x))。他说它们是等价的,而不是编译器实际将它们翻译成的。好吧,我现在同意(x:String=>f(x))是等价于f的,它们都是String=>Int。这也意味着我可以用'f _u'替换f来触发手动eta扩展,它应该仍然像f3一样工作(在REPL中尝试过,事实上就是这样). 所以我猜这个故事的寓意是,尽管对于一般的函数应用程序,它们的行为相同,但“f”和f(uu:String)并不是等价的。