String 识别由两个相等部分组成的单词
任务是识别像“abab”这样的单词,拒绝像“aacc”这样的单词。我应该使用DCG,但是我正在读的关于Prolog的书只解释了如何在原子列表上使用它们,而不是在字符串上String 识别由两个相等部分组成的单词,string,prolog,dcg,String,Prolog,Dcg,任务是识别像“abab”这样的单词,拒绝像“aacc”这样的单词。我应该使用DCG,但是我正在读的关于Prolog的书只解释了如何在原子列表上使用它们,而不是在字符串上 ?- double("abab", []). true ?- double("xyz", []). false 这是一个“家庭作业”问题,所以如果你不愿意给我答案,请随意给我一个提示。我真的不知道用谷歌搜索什么。Prolog中的字符串是字符代码列表。因此,如果您知道如何将DCG用于列表,那么您也已经知道如何将它们用于字符串。我
?- double("abab", []).
true
?- double("xyz", []).
false
这是一个“家庭作业”问题,所以如果你不愿意给我答案,请随意给我一个提示。我真的不知道用谷歌搜索什么。Prolog中的字符串是字符代码列表。因此,如果您知道如何将DCG用于列表,那么您也已经知道如何将它们用于字符串。我同意@mat的观点,即字符列表更具可读性,因此我建议您按照他在评论中的建议设置标志
也就是说,您可以使用DCG seq//1来描述任意字符串,并在DCG double//0中使用它来描述这样的字符串必须出现两次。我还建议在DCG中使用短语/2或短语/3,而不是使用DCG规则转换成的谓词(参见@mat的评论)。您可以使用短语/2定义谓词double/1,如下所示:
double(D) :- % the list D as described by
phrase(double,D). % the actual DCG double//0
seq([]) -->
[].
seq([H|T]) -->
[H],
seq(T).
double -->
seq(L),
seq(L).
查询调用谓词double/1会产生以下结果:
?- double("abab").
yes
?- double("xyz").
no
?- double("aacc").
no
?- double(D).
D = [] ? ;
D = [_A,_A] ? ;
D = [_A,_B,_A,_B] ? ;
D = [_A,_B,_C,_A,_B,_C] ? ;
...
如果您坚持,您也可以在上述代码中使用double/2的示例查询,但我再次向您推荐@mat的注释,说明为什么不建议这样做。序言中的字符串是字符代码列表。因此,如果您知道如何将DCG用于列表,那么您也已经知道如何将它们用于字符串。我同意@mat的观点,即字符列表更具可读性,因此我建议您按照他在评论中的建议设置标志
也就是说,您可以使用DCG seq//1来描述任意字符串,并在DCG double//0中使用它来描述这样的字符串必须出现两次。我还建议在DCG中使用短语/2或短语/3,而不是使用DCG规则转换成的谓词(参见@mat的评论)。您可以使用短语/2定义谓词double/1,如下所示:
double(D) :- % the list D as described by
phrase(double,D). % the actual DCG double//0
seq([]) -->
[].
seq([H|T]) -->
[H],
seq(T).
double -->
seq(L),
seq(L).
查询调用谓词double/1会产生以下结果:
?- double("abab").
yes
?- double("xyz").
no
?- double("aacc").
no
?- double(D).
D = [] ? ;
D = [_A,_A] ? ;
D = [_A,_B,_A,_B] ? ;
D = [_A,_B,_C,_A,_B,_C] ? ;
...
如果您坚持,您也可以在上述代码中使用双引号/2的示例查询,但我再次向您推荐@mat的注释,说明为什么不建议这样做。最好使用
:-set_prolog_标志(双引号,字符)。
在源文件中:这意味着双引号字符串是原子列表,因此,在您的案例中,您可以通过编写“abab”
和“xyz”
来方便地对列表进行推理,这很好。我强烈建议设置此标志,因为它可以非常方便地对此类列表进行推理,并且可以让顶级答案非常可读。使用字符比使用代码要好得多。最好使用:-set_prolog\u flag(双引号,字符)。
在源文件中:这意味着双引号字符串是原子列表,因此您可以通过编写“abab”方便地对列表进行推理
和“xyz”
@mat太棒了。我强烈建议设置此标志,因为它可以非常方便地对此类列表进行推理,并且可以让顶级答案非常可读。使用字符比使用代码要好得多。书中说DCG在差异列表匹配器中被删除,所以你使用它们就像使用差异列表谓词一样,这意味着包括额外的参数。。。。这不是“原子列表”,而是“字符列表”,它们是“长度为1的原子列表”@LukaHorvat:这本书并没有给出完整的情况:这只是在Prolog系统中实现DCG的一种特殊方法。没有什么可以阻止系统使用完全不同的实现。事实上,DCG甚至不需要编译成Prolog子句,而是可以动态解释。因此,不能保证有任何额外的参数可用。在使用DCG时,始终使用短语/[2,3]
接口谓词,就像TA那样。@LukaHorvat:当然,我很傻。我甚至没有考虑使用DCGS没有短语[/2,3]。参见mat的评论,为什么这样更好。无论如何,感谢您的澄清,我相应地更新了我的答案。@false:关于您的第一条评论:如果我没有包括:-set_prolog\u flag(双引号,字符)。
在我的.yaprc
中,我会得到字符串作为字符代码列表:“ab”=[97,98]
。设置该标志后,我得到了“ab”=[a,b]
。因此,默认情况下,字符串是字符代码列表。关于你的第二条评论:谢谢你的更正,我相应地修改了我的措辞:-)这本书说DCG在diff-list匹配器中被去除,所以你使用它们就像使用diff-list谓词一样,这意味着包括额外的参数。。。。这不是“原子列表”,而是“字符列表”,它们是“长度为1的原子列表”@LukaHorvat:这本书并没有给出完整的情况:这只是在Prolog系统中实现DCG的一种特殊方法。没有什么可以阻止系统使用完全不同的实现。事实上,DCG甚至不需要编译成Prolog子句,而是可以动态解释。因此,不能保证有任何额外的参数可用。在使用DCG时,始终使用短语/[2,3]
接口谓词,就像TA那样。@LukaHorvat:当然,我很傻。我甚至没有考虑使用DCGS没有短语[/2,3]。参见mat的评论,为什么这样更好。无论如何,感谢您的澄清,我相应地更新了我的答案。@false:关于您的第一条评论:如果我没有包括:-set_prolog\u flag(双引号,字符)。
在我的.yaprc
中,我会得到字符串作为字符代码列表:“ab”=[97,98]
。设置该标志后,我得到了“ab”=[a,b]
。因此,默认情况下,字符串是字符co的列表