2015-06-17 14 views
1

我想一個print命令添加到我的DCG語法,這裏是我有:如何打印命令添加到DCG語法

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 --> RR0 --> 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追加到磁帶,可以請你帶我到正確的方向?

回答

3

在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]. 
+0

不錯!仍然懷疑用' - >'作爲一個參數是否是一個好主意,兩個參數取而代之會更有啓發性。但那是OP想要的。 – false

+0

@false,謝謝。是的,在這裏使用' - >'也會讓我困惑。自從「工作起來」以後,我就一直跟着它。 – lurker

+0

@ lurker非常感謝你!非常好的解釋 – Mark