如何向 DCG 语法添加打印命令
How to add a print command to DCG syntax
我想在我的 DCG 语法中添加一个 print
命令,这是我所拥有的:
program( (R0 --> R) ) -->
[begin],instructs(( R0 --> R )),[end].
instructs( ( R0 --> R ) ) -->
instr(( R0 --> R )).
instructs( ( R0 --> R ) ) -->
instr(( R0 --> R1 )),
instructs(( R1 --> R )).
instr( ( R0 --> R ) ) -->
[ dte], { R is 2*R0}.
instr( ( R0 --> R ) ) -->
[ dto], { R is 2*R0 + 1}.
instr( ( R0 --> R ) ) -->
[ halve], { R is R0 // 2}.
要添加 print
,我需要将 R0 --> R
更改为 R0 --> OutTape
,其中 OutTape
是程序的输出。
我认为我可以做到以下几点:
program( (R0 --> OutTape) ) -->
[begin],instructs(( R --> Tape )),[end].
instructs( ( R --> Tape ) ) -->
instr(( R --> Tape )).
instructs( ( R --> Tape ) ) -->
instr(( R --> Tape)),
instructs(( R --> Tape )).
instr( ( R --> Tape ) ) -->
[ dte], { R is 2*R}. % is this a legal term?
instr( ( R --> Tape ) ) -->
[ dto], { R is 2*R + 1}.
instr( ( R --> Tape ) ) -->
[ halve], { R is R // 2}.
instr( ( R --> Tape ) ) -->
[ print], {append()}. % how to append R to Tape?
但我不知道如何将 R 附加到磁带上,能否请您指引我正确的方向?
在 Prolog 中,您不能重新分配变量。所以像 R is R // 2
这样的表达式会失败,因为在 Prolog 中,它在语义上说 *R
本身是除以 2
的整数,只有当 R
为 0 时才为真。
同样,鉴于 Tape
是一个列表,您不能继续追加到同一个列表(或磁带)。您必须提供磁带的先前状态,然后提供打印到磁带后的新状态。这需要在表示先前磁带状态的谓词中有一个额外的参数。一开始,磁带是空的,所以先验状态是[]
.
此外,虽然您的问题中没有完全解释,但看起来您可能希望 "print" 将中间结果录入磁带。这意味着您还需要携带中间结果,以便在遇到 print
指令时随时可以将其 "printed" 写入磁带。所以那将是另一个论点。
program((R0 --> Tape)) -->
% Initially, the tape is empty: []
% OutTape is needed here, not "Tape" as originally shown
% The second argument of `instructs` will have the final value,
% but we'll use `_` here since we only care about the values
% "printed" to the `OutTape`
[begin], instructs((R0 --> OutTape), _, []), [end], { reverse(OutTape, Tape) }.
instructs((R0 --> Tape), R, PrevTape) -->
instr((R0 --> Tape), R, PrevTape).
instructs((R0 --> Tape), R, PrevTape) -->
instr((R0 --> NextTape), R1, PrevTape), % NextTape is an intermediate tape state
instructs((R1 --> Tape), R, NextTape).
instr((R0 --> PrevTape), R, PrevTape ) -->
[dte], { R is 2*R0 }.
instr((R0 --> PrevTape), R, PrevTape) -->
[dto], { R is 2*R0 + 1 }.
instr((R0 --> PrevTape), R, PrevTape) -->
[halve], { R is R0 // 2 }.
instr((R --> [R|PrevTape]), R, PrevTape) -->
[print].
另外,在上面的代码中,我使用 reverse
作为一种快速的方式来按进程顺序排列磁带,从左到右,虽然我不确定这是否是您的要求。
| ?- phrase(program((3 --> Tape)), [begin, dte, dto, print, dte, print, end], []).
Tape = [13,26] ? ;
(1 ms) no
| ?-
结语
在此上下文中使用 -->
作为参数的函子,虽然在句法上是允许的,但有点不寻常并且可能会造成混淆。仅使用逗号会更规范:
program(R0, Tape) -->
% Initially, the tape is empty: []
% OutTape is needed here, not "Tape" as originally shown
% The 3rd argument of `instructs` will have the final value,
% but we'll use `_` here since we only care about the values
% "printed" to the `OutTape`
[begin], instructs(R0, OutTape, _, []), [end], { reverse(OutTape, Tape) }.
instructs(R0, Tape, R, PrevTape) -->
instr(R0, Tape, R, PrevTape).
instructs((R0, Tape, R, PrevTape) -->
instr(R0, NextTape, R1, PrevTape), % NextTape is an intermediate tape state
instructs(R1, Tape, R, NextTape).
instr(R0, PrevTape, R, PrevTape ) -->
[dte], { R is 2*R0 }.
instr(R0, PrevTape, R, PrevTape) -->
[dto], { R is 2*R0 + 1 }.
instr(R0, PrevTape, R, PrevTape) -->
[halve], { R is R0 // 2 }.
instr(R, [R|PrevTape], R, PrevTape) -->
[print].
我想在我的 DCG 语法中添加一个 print
命令,这是我所拥有的:
program( (R0 --> R) ) -->
[begin],instructs(( R0 --> R )),[end].
instructs( ( R0 --> R ) ) -->
instr(( R0 --> R )).
instructs( ( R0 --> R ) ) -->
instr(( R0 --> R1 )),
instructs(( R1 --> R )).
instr( ( R0 --> R ) ) -->
[ dte], { R is 2*R0}.
instr( ( R0 --> R ) ) -->
[ dto], { R is 2*R0 + 1}.
instr( ( R0 --> R ) ) -->
[ halve], { R is R0 // 2}.
要添加 print
,我需要将 R0 --> R
更改为 R0 --> OutTape
,其中 OutTape
是程序的输出。
我认为我可以做到以下几点:
program( (R0 --> OutTape) ) -->
[begin],instructs(( R --> Tape )),[end].
instructs( ( R --> Tape ) ) -->
instr(( R --> Tape )).
instructs( ( R --> Tape ) ) -->
instr(( R --> Tape)),
instructs(( R --> Tape )).
instr( ( R --> Tape ) ) -->
[ dte], { R is 2*R}. % is this a legal term?
instr( ( R --> Tape ) ) -->
[ dto], { R is 2*R + 1}.
instr( ( R --> Tape ) ) -->
[ halve], { R is R // 2}.
instr( ( R --> Tape ) ) -->
[ print], {append()}. % how to append R to Tape?
但我不知道如何将 R 附加到磁带上,能否请您指引我正确的方向?
在 Prolog 中,您不能重新分配变量。所以像 R is R // 2
这样的表达式会失败,因为在 Prolog 中,它在语义上说 *R
本身是除以 2
的整数,只有当 R
为 0 时才为真。
同样,鉴于 Tape
是一个列表,您不能继续追加到同一个列表(或磁带)。您必须提供磁带的先前状态,然后提供打印到磁带后的新状态。这需要在表示先前磁带状态的谓词中有一个额外的参数。一开始,磁带是空的,所以先验状态是[]
.
此外,虽然您的问题中没有完全解释,但看起来您可能希望 "print" 将中间结果录入磁带。这意味着您还需要携带中间结果,以便在遇到 print
指令时随时可以将其 "printed" 写入磁带。所以那将是另一个论点。
program((R0 --> Tape)) -->
% Initially, the tape is empty: []
% OutTape is needed here, not "Tape" as originally shown
% The second argument of `instructs` will have the final value,
% but we'll use `_` here since we only care about the values
% "printed" to the `OutTape`
[begin], instructs((R0 --> OutTape), _, []), [end], { reverse(OutTape, Tape) }.
instructs((R0 --> Tape), R, PrevTape) -->
instr((R0 --> Tape), R, PrevTape).
instructs((R0 --> Tape), R, PrevTape) -->
instr((R0 --> NextTape), R1, PrevTape), % NextTape is an intermediate tape state
instructs((R1 --> Tape), R, NextTape).
instr((R0 --> PrevTape), R, PrevTape ) -->
[dte], { R is 2*R0 }.
instr((R0 --> PrevTape), R, PrevTape) -->
[dto], { R is 2*R0 + 1 }.
instr((R0 --> PrevTape), R, PrevTape) -->
[halve], { R is R0 // 2 }.
instr((R --> [R|PrevTape]), R, PrevTape) -->
[print].
另外,在上面的代码中,我使用 reverse
作为一种快速的方式来按进程顺序排列磁带,从左到右,虽然我不确定这是否是您的要求。
| ?- phrase(program((3 --> Tape)), [begin, dte, dto, print, dte, print, end], []).
Tape = [13,26] ? ;
(1 ms) no
| ?-
结语
在此上下文中使用 -->
作为参数的函子,虽然在句法上是允许的,但有点不寻常并且可能会造成混淆。仅使用逗号会更规范:
program(R0, Tape) -->
% Initially, the tape is empty: []
% OutTape is needed here, not "Tape" as originally shown
% The 3rd argument of `instructs` will have the final value,
% but we'll use `_` here since we only care about the values
% "printed" to the `OutTape`
[begin], instructs(R0, OutTape, _, []), [end], { reverse(OutTape, Tape) }.
instructs(R0, Tape, R, PrevTape) -->
instr(R0, Tape, R, PrevTape).
instructs((R0, Tape, R, PrevTape) -->
instr(R0, NextTape, R1, PrevTape), % NextTape is an intermediate tape state
instructs(R1, Tape, R, NextTape).
instr(R0, PrevTape, R, PrevTape ) -->
[dte], { R is 2*R0 }.
instr(R0, PrevTape, R, PrevTape) -->
[dto], { R is 2*R0 + 1 }.
instr(R0, PrevTape, R, PrevTape) -->
[halve], { R is R0 // 2 }.
instr(R, [R|PrevTape], R, PrevTape) -->
[print].