Prolog 序言+;clpfd:带值的简单二进制数解析器

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, []).

我目前正在尝试理解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, []).
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:这样的突出显示经常被“编辑”删除。很难证明它用于的合理性,但在这样的情况下几乎是不可能的(这种情况与其他编程语言非常相似)。