Erlang 理解递归:递归地查找子字符串是否是字符串的前缀

Erlang Understanding recursion: Find if substring is prefix of string recursively

我想了解这个在字符串中查找前缀的实现,它的实现没有使用任何内置的列表函数,而是使用递归遍历字符串。

尝试:

checkStringPrefix([C|StringTail],[C|LookupTail]) ->
checkStringPrefix(StringTail,LookupTail);

checkStringPrefix(_,[]) ->                            
    "***";                                    

checkStringPrefix(_String,_Lookup) ->                    
    "".                                         

有效,该函数递归调用自身,将第一个字符与尾部分开。

调用示例:

1> stringUtil:checkStringPrefix("test xxxxx", "test").
"***"
2> stringUtil:checkStringPrefix("test xxxxx", "testtt"). 
[]

在两个不相等字符的情况下,将调用最后一个函数变体。 我不完全理解这个概念,我希望得到解释。我理解递归迭代的过程,我不明白为什么第二个变体在正确的时刻被调用。

考虑将单个字符串或空字符串作为参数传递时会发生什么:

  • 传递 "a""a":这会调用 checkStringPrefix/2 的第一个子句,因为在其函数头中显式匹配两个参数的第一个元素,这也强制两个参数都不能是空列表。这个子句递归调用函数,因为两个参数都没有尾部,第二个函数子句被调用,因为第二个参数匹配空列表,所以结果是 "***".
  • 传递 "a""b":这不会调用第一个子句,因为第一个元素不匹配,也不会调用第二个子句,因为第二个参数不匹配空列表。因此它调用了第三个子句,所以结果是 "".
  • 传递"""":这不会调用第一个子句,因为两个参数都是空列表;它调用第二个子句,因为第二个参数匹配空列表,所以结果是 "***"。事实上,由于第二个子句将其第一个参数视为无关紧要,因此即使第一个参数不为空,同样的分析也适用。
  • 传递"""a":这不会调用第一个子句,因为第一个参数为空,也不会调用第二个子句,因为第二个参数不为空,所以它调用第三个子句,结果是 "".

无论两个参数字符串的长度如何,这些都是每次调用的选择。

为了回答您关于何时调用第二个函数子句的具体问题,只要第二个参数为空列表,就会发生这种情况,因为函数头中该情况的特定匹配,并且该函数头也忽略了第一个参数。匹配按照声明的顺序进行;第一个函数子句要求两个参数都至少有一个元素,因此当第二个参数为空列表时,它无法匹配第一个子句,因此匹配第二个子句。