FP模式匹配

时间:2016-09-29 14:00:01

标签: scala

我刚开始用Scala学习FP,所以为这个问题道歉。我发现这个练习(练习3.1 https://www.scala-exercises.org/fp_in_scala/functional_data_structures)用于模式匹配,但是我有点困惑并且很难理解X的结果是3的结果。

val x = List(1, 2, 3, 4, 5) match {
  case Cons(x, Cons(2, Cons(4, _))) => x
  case Nil => 42
  case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y
  case Cons(h, t) => h + sum(t)
  case _ => 101
}

有些人可以协助一步一步地调试这个场景吗?我相信这将有助于我理解这个概念。

感谢。

5 个答案:

答案 0 :(得分:3)

Scala中的不可变ListCons - 列表。这意味着它由一系列Cons - 对象组成,并以Nil结尾。例如,您的列表:

List(1, 2, 3, 4, 5)

将是Cons - 列表:

Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))

在Scala中对列表进行模式匹配时,可以使用此Cons - 结构。这就是那个例子。

让我通过每个模式告诉你他们做了什么:

  1. 如果您的第二个元素是2并且您的第三个元素是4,那么这个匹配。如果是这种情况,表达式将返回列表的第一个元素。 _表示您忽略列表的其余部分(因此它可能是3个元素或更多)。

    case Cons(x, Cons(2, Cons(4, _))) => x
    
  2. 这个匹配空列表。如果匹配,则表达式返回42.

    case Nil => 42
    
  3. 如果您的第三个元素是3并且您的第四个元素是4,则匹配该值。如果匹配,则表达式返回列表中两个第一个元素的总和。

    case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y
    
  4. 此匹配至少包含一个元素的所有列表。如果匹配,则表达式返回第一个元素加上列表其余部分的总和(基本上等于整个列表的总和)。

    case Cons(h, t) => h + sum(t)
    
  5. 这个匹配其他所有内容。这是默认情况,并返回101.这绝不会发生,因为所有其他情况都在其上面。

    case _ => 101
    
  6. 正如您希望现在可以看到的那样,x的值变为3,因为它与第三种情况匹配。这将返回1 + 2,等于3。

答案 1 :(得分:1)

{ "_id" : "003", "_class" : "nl.kamans.Floor", "name" : "FloorDemo", "tiles" : [ { "_id" : "035", "sensors" : [ { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false } ], "x" : 0, "y" : 0, "batteryVoltage" : 0, "orientation" : "NORTH", "nodeType" : "WIRELESS" }, { "_id" : "042", "sensors" : [ { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false } ], "x" : 1, "y" : 0, "batteryVoltage" : 0, "orientation" : "NORTH", "nodeType" : "WIRELESS" }, { "_id" : "049", "sensors" : [ { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false } ], "x" : 2, "y" : 0, "batteryVoltage" : 0, "orientation" : "NORTH", "nodeType" : "WIRELESS" }, { "_id" : "007", "sensors" : [ { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false } ], "x" : 3, "y" : 0, "batteryVoltage" : 0, "orientation" : "NORTH", "nodeType" : "WIRELESS" }, { "_id" : "029", "sensors" : [ { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false } ], "x" : 0, "y" : 1, "batteryVoltage" : 0, "orientation" : "NORTH", "nodeType" : "WIRELESS" }, { "_id" : "021", "sensors" : [ { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false } ], "x" : 1, "y" : 1, "batteryVoltage" : 0, "orientation" : "NORTH", "nodeType" : "WIRELESS" }, { "_id" : "014", "sensors" : [ { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false }, { "state" : false, "ignored" : false } ], "x" : 2, "y" : 1, "batteryVoltage" : 0, "orientation" : "NORTH", "nodeType" : "WIRELESS" } ], "height" : 1, "width" : 3, "defined" : true, "lastUpdate" : ISODate("2016-09-29T13:26:40.866Z") 匹配模式List(1, 2, 3, 4, 5)

此处Cons(x, Cons(y, Cons(3, Cons(4, _))))对应于x1对应于2,3和4,并忽略了最后一个元素。

所以y

说明

列表与第一个模式(x + y = 1 + 2)不匹配,因为2个模式后有4个

列表与Cons(x, Cons(2, Cons(4, _)))的第二个模式不匹配,因为列表不是Nil

列表匹配第三种模式

当一个模式匹配时...其他情况不匹配。所以模式匹配在第3个案例(成功匹配)后停止匹配

答案 2 :(得分:0)

列表(1,2,3,4,5)等于Cons(1,Cons(2,Cons(3,Cons(4,Cons(5,Nil))))。

val x = List(1, 2, 3, 4, 5) match {
      case Cons(x, Cons(2, Cons(4, _))) => x //1
      case Nil => 42  //2
      case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y //3
      case Cons(h, t) => h + sum(t) //4 
      case _ => 101 //5
}

" _"性格意味着“不要关心”

了解提供模式的第一个匹配会影响结果非常重要。

  1. 不能,因为它的缺点(2,缺点( 3 ,缺点(4,......)))
  2. 不能,因为它不是Nil,它的缺点
  3. 这是提供模式,因为 x 可以等于1, y 等于2,其余的按原样继续。当他看到" _"他并不关心他所看到的意味着它所提供的

答案 3 :(得分:0)

正如您可以通过名称pattern-matching猜测,case中提供的整个表达式被视为Pattern,并与匹配的值匹配。

在这种情况下,您的匹配值为List(1, 2, 3, 4, 5)。列表也可以使用infix cons - ::(或postfix cons - Cons)来表示。

因此,此列表可以表示为(使用infix cons),

1 :: 2 :: 3 :: 4 :: 5 :: Nil

或(使用postfix cons),

Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil))))`

因此您可以看到它与模式Cons(x, Cons(y, Cons(3, Cons(4, _))))匹配,因此x与值1y匹配到值2,这使得结果x + y3

答案 4 :(得分:0)

该列表与第三种情况相符,这就是您正在查看的内容。两个“列表”中的模式是相同的。因此,第三种情况将产生x + y的结果,在这种情况下为3.要查看它,请回顾原始参数List(1, 2, 3, 4, 5)并观察它与第三种情况的匹配情况; x = 1y = 2;所以x + y = 3