在展平函数中使用的模式匹配中的列表[_]的说明

Don*_*beo 2 scala pattern-matching partial-functions flatmap

我是scala的新手,我无法理解以下功能

val L = List(List(1, 1), 2, List(3, List(5, 8)))       

def flatten(l: List[Any]): List[Any] =  l flatMap {
    case ms:List[_] => flatten(ms)
    case l => List(l)
}                                         

flatten(L)                      // res2: List[Any] = List(1, 1, 2, 3, 5, 8)
Run Code Online (Sandbox Code Playgroud)

特别是我不理解第一种情况的组合flatMap和模式匹配以及意义ms:List[_]

有人可以解释一下,也许可以提供一个更简单的例子来澄清这个概念吗?

Nad*_*ari 16

mapflatMap

首先flatMap高阶函数.

map也是一个更高阶的函数,它通过对其中的所有元素应用函数将a转换List为new .例如,如果你有ListList

val l = List(1,2,3)
Run Code Online (Sandbox Code Playgroud)

你可以使用map它到一个新的列表

val doubled = l.map(_ * 2)         // List(2,4,6)
Run Code Online (Sandbox Code Playgroud)

那是什么flatMapflatMap当你的函数得到一个Int但返回一个时,它很有用List[Int].在这种情况下,如果你将这个函数传递给map你得到的将是一个List[List[Int]]但有时你想要得到一个List[Int].

你可以做的是flatMap改用.在数学上它等同于第一个map然后flatten是结果,但在行动中它可以flatten是基于flatMap不相反的方式定义的函数.

除了技术细节,flatten意味着如果你有List[List[List...[Int]]],如果你flatten有,你会得到一个List[Int].

我们看的时候

def flatten(l: List[Any]): List[Any] =  l flatMap {
    case ms:List[_] => flatten(ms)
    case l => List(l)
} 
Run Code Online (Sandbox Code Playgroud)

我们首先需要知道这是什么意思.我们已经知道我们必须将函数传递给flatMap.在这种情况下,我们传递的函数是

{
    case ms:List[_] => flatten(ms)
    case l => List(l)
} 
Run Code Online (Sandbox Code Playgroud)

起初看起来不像是一个功能,但它是!它实际上是一个部分功能,您可以将其视为具有一些细微差别的功能!

什么是部分功能?

我们可以通过以下方式获得(几乎)相同的结果:

def flatten(l: List[Any]): List[Any] =  l flatMap { _ match {
        case ms:List[_] => flatten(ms)
        case l => List(l)
    }   
}
Run Code Online (Sandbox Code Playgroud)

普通函数和部分函数之间的区别在于某些特定输入可能未定义部分函数.所以编译器会自动从一个以case关键字开头的主体生成一个部分函数(它不是那么简单,但为了简单起见,我在这里跳过细节).

类型匹配模式

类似的模式ms:List[_]称为类型模式.这意味着ms将在运行时检查类型List[_]._是一个外卡并且意味着任何类型,因此ms:List[_]字面意思是List任何类型(由于类型擦除你不能使用类似的模式ms:List[Int],请参阅线程获取更多信息).

因此,此代码片段上的整个模式匹配意味着

  • 如果ms是列表,结果将是flatten(ms),否则结果将是List(l).

flatten像这样定义的函数是递归函数,它解包列表并执行此操作直到没有更多列表,然后它将结果再次包装在一个List!这种方式List[List[List.......[_]]]将转换为List[_].

类型模式的另一个例子:

def hello(o: Any) = o match {
    case _:Int => "Hi, I am an Int and I'm proud of it!"
    case _:List[_] => "I have many things to tell you! I am a list after all!"
    case b:Boolean => s"I'm simply a flag and my value is $b"
    case _ => "I'm everything else you can imagine :D"
}
Run Code Online (Sandbox Code Playgroud)

消歧

顺便说一下,部分功能部分应用功能和部分应用完全不同!

Scala中的部分函数的概念与数学中的部分函数相同:对于其域的某些值可能未定义的函数.