在Prolog中,您不能重新分配變量。所以表達式,如R is R // 2
以來,在序言中,語義上說,* R
本身由2
整數除法,因爲這隻會是真實的,如果R
爲0
同樣,因爲一個Tape
是一個列表會失敗,你不能繼續附加到相同的列表(或磁帶)。您必須提供磁帶的先前狀態,然後在打印到磁帶後提供新狀態。這需要在謂詞中表示之前磁帶狀態的額外參數。在開始時,磁帶是空的,因此之前的狀態是[]
。
另外,雖然在你的問題中沒有完全解釋它,但看起來你可能想把中間結果打印到磁帶上。這意味着您還需要攜帶中間結果,以便在遇到任何print
指令時將其「打印」到磁帶上。所以這將是另一個論點。
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].
不錯!仍然懷疑用' - >'作爲一個參數是否是一個好主意,兩個參數取而代之會更有啓發性。但那是OP想要的。 – false
@false,謝謝。是的,在這裏使用' - >'也會讓我困惑。自從「工作起來」以後,我就一直跟着它。 – lurker
@ lurker非常感謝你!非常好的解釋 – Mark