我刚开始用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
}
有些人可以协助一步一步地调试这个场景吗?我相信这将有助于我理解这个概念。
感谢。
答案 0 :(得分:3)
Scala中的不可变List
是Cons
- 列表。这意味着它由一系列Cons
- 对象组成,并以Nil
结尾。例如,您的列表:
List(1, 2, 3, 4, 5)
将是Cons
- 列表:
Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))
在Scala中对列表进行模式匹配时,可以使用此Cons
- 结构。这就是那个例子。
让我通过每个模式告诉你他们做了什么:
如果您的第二个元素是2并且您的第三个元素是4,那么这个匹配。如果是这种情况,表达式将返回列表的第一个元素。 _
表示您忽略列表的其余部分(因此它可能是3个元素或更多)。
case Cons(x, Cons(2, Cons(4, _))) => x
这个匹配空列表。如果匹配,则表达式返回42.
case Nil => 42
如果您的第三个元素是3并且您的第四个元素是4,则匹配该值。如果匹配,则表达式返回列表中两个第一个元素的总和。
case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y
此匹配至少包含一个元素的所有列表。如果匹配,则表达式返回第一个元素加上列表其余部分的总和(基本上等于整个列表的总和)。
case Cons(h, t) => h + sum(t)
这个匹配其他所有内容。这是默认情况,并返回101.这绝不会发生,因为所有其他情况都在其上面。
case _ => 101
正如您希望现在可以看到的那样,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, _))))
对应于x
,1
对应于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
}
" _"性格意味着“不要关心”
了解提供模式的第一个匹配会影响结果非常重要。
答案 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
与值1
和y
匹配到值2
,这使得结果x + y
为3
。
答案 4 :(得分:0)
该列表与第三种情况相符,这就是您正在查看的内容。两个“列表”中的模式是相同的。因此,第三种情况将产生x + y
的结果,在这种情况下为3.要查看它,请回顾原始参数List(1, 2, 3, 4, 5)
并观察它与第三种情况的匹配情况; x = 1
和y = 2
;所以x + y = 3
。