首先考虑以下代码,它计算字符串中的空格数:
countSpaces :: String -> Int
countSpaces [] = 0
countSpaces (c : restOfString)
= d + countSpaces restOfString
where d = if c == ’ ’ then 1
else 0
以下是我的问题:
1,如果我拨打电话:countSpaces "abc"
,那么当此函数尝试将字符串"abc"
与(c: restOfString)
匹配时会发生什么。我的意思是,restOfString
在此次调用中为:"abc"
,但(c:restOfString)
是什么?你正在“消耗”某些东西(变量?c
)到restOfstring
然后你想要匹配?我只是不明白。
2,我尝试运行代码但是我得到一个解析错误原因?
在输入'''
上解析错误
3,此函数会将countSpaces
调用为无穷大吗?因为restOfString
总是相同而不是减少,例如。拨打电话countSpaces "aaa"
在第一次通话,第二次或任何通话后都不会改变,对吗?
现在考虑完成相同任务的代码:
countSpaces :: String -> Int
countSpaces [] = 0
countSpaces (’ ’ : restOfString)
= 1 + countSpaces restOfString
countSpaces (_ : restOfString)
= 0 + countSpaces restOfString
1,所以如果我们尝试拨打电话countSpaces "abc"
,模式(’ ’ : restOfString)
会变得更大,因为每次countSpaces
被调用时,这只会导致' '
到restOfString
countSpaces
,除非每次调用' '
,否则字符串中的第一个字符将更改为:countSpaces "abc"
。因此,在(’ ’ : restOfString)
的第一次调用中,' ':"bc"
为"a"
,这是令人困惑的,因为它将" abc"
替换为空白而不是将其删除,以便我们得到:{ {1}}
答案 0 :(得分:6)
1,如果我打电话:countSpaces“abc”,那么当这个函数试图将字符串“abc”与:(c:restOfString)匹配时会发生什么。
当您使用cons运算符:
匹配该模式时,:
左侧的元素是列表中的第一个元素,而:
右侧的元素是余数的清单。以下是等效的:
"abc" == 'a' : "bc"
由于String
是一个字符列表(具体来说,[Char]
),因此上述内容也可以写成:
"abc" == 'a' : 'b' : 'c' : []
2,我尝试运行代码但是我得到一个解析错误原因?
您的解析错误是因为您对单引号使用了错误的字符。当您使用unicode 0x2019
时,您正在使用ASCII/Unicode Apostrophe character:'
3,这个函数会将countSpaces调用到无穷大吗?
如果你的字符串是无限的,它只会计入无穷大。减少实际上发生在这一部分:
countSpaces restOfString
要了解原因,请参阅第1部分的答案。对于“abc”,restOfString
为“bc”。
4,所以如果我们尝试调用countSpaces“abc”模式:('':restOfString)将变得更大,因为每次countSpaces被调用时,这只会对'restOfString有一个'',除非每次countSpaces都会得到调用然后字符串中的第一个字符将更改为:''。所以在第一次调用countSpaces“abc”然后('':restOfString)是'':“bc”,这是混淆吧?
我认为您的混淆源于模式匹配和构建列表看起来相同的事实。即,当你写(' ':restOfString)
时会发生什么,完全取决于背景。
您可以将函数定义视为分为由=
符号分隔的两个部分:
countSpaces (' ' : restOfString) = 1 + countSpaces restOfString
^ ^ ^ ^ ^
| | | | |
-------------------------------- | ----------------------------
| | |
Pattern Matching Separator Function Body
模式匹配部分不会影响输出。当您在模式匹配方面使用(' ' : restOfString)
时,您会说,“如果传递给countSpaces
函数的参数以空格开头,则返回此函数体中的内容。如果第一个字符是不是空格,然后尝试定义的下一个模式“。在任何一种情况下(无论是否匹配),传递给countSpaces
的值都不会以任何方式被修改(它没有放在它前面的空格;这种事情只发生在函数体中)。
相反,当你将(' ' : restOfString)
放在函数体中时,你会说“返回带有空格字符前缀的restOfString
”。