【问题标题】:Comparing with List Patterns与列表模式比较
【发布时间】:2016-04-29 17:18:09
【问题描述】:

首先考虑以下代码,它计算字符串中空格的数量:

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) 是什么?您正在向restOfstring 'consing' 某些东西(变量?c),然后您尝试匹配?我就是不明白。

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,除非每次@ 987654339@ 将被调用,字符串中的第一个字符将更改为:' '。所以在countSpaces "abc" 的第一次调用中,(’ ’ : restOfString)' ':"bc",这很令人困惑,因为它用空白代替了 "a",而不是使用它,所以我们得到:" abc"

【问题讨论】:

  • "abc" 只是['a', 'b', 'c']'a':'b':'c':[] 的语法糖。
  • 你使用了奇怪的撇号。比较一下:' 和你的 。他们是不同的角色。

标签: haskell pattern-matching


【解决方案1】:

1,如果我调用:countSpaces "abc" ,那么当这个函数尝试将字符串 "abc" 与: (c: restOfString) 匹配时会发生什么。

当您使用 cons 运算符 : 匹配该模式时,: 左侧的元素是列表中的第一个元素,: 右侧是列表的其余部分。以下是等价的:

"abc" == 'a' : "bc"

由于String 是一个字符列表(具体来说,[Char]),上面也可以写成:

"abc" == 'a' : 'b' : 'c' : []

2,我尝试运行代码,但出现解析错误,为什么?

您的解析错误是因为您对单引号使用了错误的字符。当你应该使用ASCII/Unicode Apostrophe character: '时,你正在使用unicode 0x2019

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 值”。

【讨论】:

  • 好的,这让我感到困惑:如果我们将: c 更改为 'c' 是否意味着您会将 restOfList 中的第一个元素更改为 'c' ?但是 ('c':"ab") 会产生 "cab"。如果它是参数(如在此函数中)或字符串(不是调用的参数),则结果会有所不同@Chad Gilberg
  • ('c':"ab") 在模式匹配的上下文中将匹配字符串“cab”。如果您改为返回 ('c':"ab"),那么您将返回字符串“cab”。请记住,c 是一个变量名,'c' 是一个 Char,因为它被单引号括起来。
  • countSpaces (' ' : restOfString) = 1 + countSpaces restOfStringcountSpaces (_ : restOfString) = 0 + countSpaces restOfString 是通过模式匹配解决问题的有效方法。
  • 不好意思问了这么多问题,我只是想了解一下,希望大家多多包涵:)。我在上面的主要问题中更改(添加),也许你可以看看:) @Chad Gillberg
  • 我已经添加了对我的回答的回复,希望能更清楚地说明模式匹配和函数体之间的区别。
猜你喜欢
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
  • 2021-07-14
  • 2018-11-18
相关资源
最近更新 更多