Prolog 序言+;clpfd:带值的简单二进制数解析器
我目前正在尝试理解prolog中的DCGs 考虑这个例子Prolog 序言+;clpfd:带值的简单二进制数解析器,prolog,dcg,clpfd,Prolog,Dcg,Clpfd,我目前正在尝试理解prolog中的DCGs 考虑这个例子 digit(0) --> "0". digit(1) --> "1". binaryNumber(Val) --> digit(Val). binaryNumber(Next*2 + Cur) --> %CurVal #= Cur + Next*2, binaryNumber(Next), digit(Cur). 这将产生: 207 ?- binaryNumber(X, Y, []).
digit(0) --> "0".
digit(1) --> "1".
binaryNumber(Val) --> digit(Val).
binaryNumber(Next*2 + Cur) -->
%CurVal #= Cur + Next*2,
binaryNumber(Next),
digit(Cur).
这将产生:
207 ?- binaryNumber(X, Y, []).
X = 0,
Y = [48] ;
X = 1,
Y = [49] ;
X = 0*2+0,
Y = [48, 48] ;
X = 0*2+1,
Y = [48, 49] ;
X = 1*2+0,
Y = [49, 48] ;
X = 1*2+1,
Y = [49, 49] ;
X = (0*2+0)*2+0,
这很好
但是,如果要将字符串“转换”为值:
:- use_module(library(clpfd)).
digit(0) --> "0".
digit(1) --> "1".
binaryNumber(Val) --> digit(Val).
binaryNumber(CurVal) -->
CurVal #= Cur + Next*2,
binaryNumber(Next),
digit(Cur).
我得到:
209 ?- binaryNumber(X, Y, []).
X = 0,
Y = [48] ;
X = 1,
Y = [49] ;
ERROR: binaryNumber/3: Undefined procedure: (#=)/4
ERROR: However, there are definitions for:
ERROR: (#=)/2
Exception: (7) #=(_G4807345, _G4807428+_G4807431*2, _G4807346, _G4807475) ?
两个问题:
binaryNumber
希望#=
的“arity”为4李>
foo//n
不是“直接”实现的,而是通过将语法foo//n
转换为相应的Prolog谓词foo//(n+2)
。这种转换是通过一种类似于其他语言中宏的机制来完成的。通常,你根本不必介意
欲了解更多信息,请阅读:(1)和(2)问题 ”“还有这个问题的答案
回到主题,我看到您在使用中存在两个问题:
{}/1
,,
因此,在前面提到的“语法到谓词”翻译步骤中,它们被跳过。在你的代码中,你不想使用(#=)/2
(又称(#=)/4
),你想要(#=)/2
foo/(n+2)
目标是很好的实践,而不是。
使用或用于此binaryNumber(Next*10 + Cur) -->
{ CurVal #= Cur + Next*2 },
binaryNumber(Next),
digit(Cur).
现在让我们提问
?- phrase(binaryNumber(X),Ts).
X = 0, Ts = [48] ;
X = 1, Ts = [49] ;
X = 0, Ts = [48,48] ;
X = 1, Ts = [48,49] ;
X = 2, Ts = [49,48] ;
X = 3, Ts = [49,49] ...
相关:,@false:如果你对此感兴趣,那么这个例子是合成的,用于训练。也就是说,我对“如何将字符串转换为数字”不感兴趣,而是对“如何在prolog中使用DCG作为解析器”感兴趣。但DCG正是在这里将某些东西的列表“转换”为其他东西,反之亦然。@false:意思是说,对于字符串数字转换,通常有实用函数。所以另一个人可能一直在寻找这个函数,而我在寻找对dcgs的理解。稍微不同的问题…@SigTerm。尝试更改第二个子句中的
数字
和二进制数
的顺序。如果您使用新版本的SWI Prolog,请确保使用选项--“传统”启动它@重复:好的,很公平。如果我在这个问题上仍然需要帮助,我会发布新的问题(相当肯定我可以通过引入“中间人”谓词来反转字符串)。谢谢你的帮助/玩得开心。@repeat:在这个例子中,发表评论会更好。也就是说,如果可以用注释来表达,从而获得更好的结果,那么就使用注释。在a中,我确实使用了
和
,但如果不使用它们,代码的可读性会降低,并且带有注释的代码会更大。那么二进制数//1
的终止在我看来是非常不终止的。(我没有研究细节,我只是错过了一些对变量的合理限制)。@mat:这样的突出显示经常被“编辑”删除。很难证明它用于的合理性,但在这样的情况下几乎是不可能的(这种情况与其他编程语言非常相似)。